<!DOCTYPE html>
<!-- Ported from the OpenGL Samples Pack https://github.com/g-truc/ogl-samples/blob/master/tests/gl-320-texture-format.cpp -->
<html lang="en">

<head>
    <title>WebGL 2 Samples - texture_format</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <div id="info">WebGL 2 Samples - texture_format</div>
    <p id="description">
        This sample demonstrates loading a variety of texture formats (view source for details).
    </p>

    <!-- WebGL 2 shaders -->
    <script id="vs" type="x-shader/x-vertex">
        #version 300 es
        #define POSITION_LOCATION 0
        #define TEXCOORD_LOCATION 4
        
        precision highp float;
        precision highp int;

        uniform mat4 MVP;

        layout(location = POSITION_LOCATION) in vec2 position;
        layout(location = TEXCOORD_LOCATION) in vec2 texcoord;

        out vec2 v_st;

        void main()
        {
            v_st = texcoord;
            gl_Position = MVP * vec4(position, 0.0, 1.0);
        }
    </script>

    <script id="fs-normalized" type="x-shader/x-fragment">
        #version 300 es
        precision highp float;
        precision highp int;

        uniform sampler2D diffuse;

        in vec2 v_st;

        out vec4 color;

        void main()
        {
            color = texture(diffuse, v_st);
        }
    </script>

    <script id="fs-uint" type="x-shader/x-fragment">
        #version 300 es
        precision highp float;
        precision highp int;
        precision highp usampler2D;

        uniform usampler2D diffuse;

        in vec2 v_st;

        out vec4 color;

        void main()
        {
            ivec2 size = textureSize(diffuse, 0);
            vec2 texcoord = v_st * vec2(size);
            ivec2 coord = ivec2(texcoord);
            uvec4 texel = uvec4(texelFetch(diffuse, coord, 0));

            color = vec4(texel) / 255.0;
        }
    </script>

    <script src="utility.js"></script>
    <script>
    (function () {
        'use strict';

        var canvas = document.createElement('canvas');
        canvas.width = Math.min(window.innerWidth, window.innerHeight);
        canvas.height = canvas.width;
        document.body.appendChild(canvas);

        var gl = canvas.getContext( 'webgl2', { antialias: false } );
        var isWebGL2 = !!gl;
        if(!isWebGL2) {
            document.getElementById('info').innerHTML = 'WebGL 2 is not available.  See <a href="https://www.khronos.org/webgl/wiki/Getting_a_WebGL_Implementation">How to get a WebGL 2 implementation</a>';
            return;
        }

        // -- Viewport

        var windowSize = {
            x: canvas.width,
            y: canvas.height
        };

        var Views = {
            BOTTOM_LEFT: 0,
            BOTTOM_CENTER: 1,
            BOTTOM_RIGHT: 2,
            MIDDLE_LEFT: 3,
            MIDDLE_CENTER: 4,
            MIDDLE_RIGHT: 5,
            TOP_LEFT: 6,
            TOP_CENTER: 7,
            TOP_RIGHT: 8,
            MAX: 9
        };

        var viewport = new Array(Views.MAX);

        for (var i = 0; i < Views.MAX; ++i) {
            var row = Math.floor(i / 3);
            var col = i % 3;
            viewport[i] = {
                x: windowSize.x * col / 3.0,
                y: windowSize.y * row / 3.0,
                z: windowSize.x / 3.0,
                w: windowSize.y / 3.0
            };
        }

        // -- Init program
        var programUint = createProgram(gl, getShaderSource('vs'), getShaderSource('fs-uint'));
        var mvpUintLocation = gl.getUniformLocation(programUint, 'MVP');
        var diffuseUintLocation = gl.getUniformLocation(programUint, 'diffuse');

        var programNormalized = createProgram(gl, getShaderSource('vs'), getShaderSource('fs-normalized'));
        var mvpNormalizedLocation = gl.getUniformLocation(programNormalized, 'MVP');
        var diffuseNormalizedLocation = gl.getUniformLocation(programNormalized, 'diffuse');

        // -- Init buffers: vec2 Position, vec2 Texcoord
        var positions = new Float32Array([
            -1.0, -1.0,
             1.0, -1.0,
             1.0,  1.0,
             1.0,  1.0,
            -1.0,  1.0,
            -1.0, -1.0
        ]);
        var vertexPosBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
        gl.bindBuffer(gl.ARRAY_BUFFER, null);

        var texCoords = new Float32Array([
            0.0, 1.0,
            1.0, 1.0,
            1.0, 0.0,
            1.0, 0.0,
            0.0, 0.0,
            0.0, 1.0
        ]);
        var vertexTexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, texCoords, gl.STATIC_DRAW);
        gl.bindBuffer(gl.ARRAY_BUFFER, null);

        // -- Init VertexArray
        var vertexArray = gl.createVertexArray();
        gl.bindVertexArray(vertexArray);

        var vertexPosLocation = 0; // set with GLSL layout qualifier
        gl.enableVertexAttribArray(vertexPosLocation);
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
        gl.vertexAttribPointer(vertexPosLocation, 2, gl.FLOAT, false, 0, 0);
        gl.bindBuffer(gl.ARRAY_BUFFER, null);

        var vertexTexLocation = 4; // set with GLSL layout qualifier
        gl.enableVertexAttribArray(vertexTexLocation);
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexBuffer);
        gl.vertexAttribPointer(vertexTexLocation, 2, gl.FLOAT, false, 0, 0);
        gl.bindBuffer(gl.ARRAY_BUFFER, null);

        gl.bindVertexArray(null);

        loadImage('../assets/img/Di-3d.png', function(image) {
            var TextureTypes = {
                RGB: 0,
                RGB8: 1,
                RGBA: 2,
                RGB16F: 3,
                RGBA32F: 4,
                R16F: 5,
                RG16F: 6,
                RGB8UI: 7,
                RGBA8UI: 8,
                MAX: 9
            };

            var textureFormats = new Array(TextureTypes.MAX);

            textureFormats[TextureTypes.RGB] = {
                internalFormat: gl.RGB,
                format: gl.RGB,
                type: gl.UNSIGNED_BYTE
            };

            textureFormats[TextureTypes.RGB8] = {
                internalFormat: gl.RGB8,
                format: gl.RGB,
                type: gl.UNSIGNED_BYTE
            };

            textureFormats[TextureTypes.RGB16F] = {
                internalFormat: gl.RGB16F,
                format: gl.RGB,
                type: gl.HALF_FLOAT
            };

            textureFormats[TextureTypes.RGBA32F] = {
                internalFormat: gl.RGBA32F,
                format: gl.RGBA,
                type: gl.FLOAT
            };

            textureFormats[TextureTypes.R16F] = {
                internalFormat: gl.R16F,
                format: gl.RED,
                type: gl.HALF_FLOAT
            };

            textureFormats[TextureTypes.RG16F] = {
                internalFormat: gl.RG16F,
                format: gl.RG,
                type: gl.HALF_FLOAT
            };

            textureFormats[TextureTypes.RGBA] = {
                internalFormat: gl.RGBA,
                format: gl.RGBA,
                type: gl.UNSIGNED_BYTE
            };

            textureFormats[TextureTypes.RGB8UI] = {
                internalFormat: gl.RGB8UI,
                format: gl.RGB_INTEGER,
                type: gl.UNSIGNED_BYTE
            };

            textureFormats[TextureTypes.RGBA8UI] = {
                internalFormat: gl.RGBA8UI,
                format: gl.RGBA_INTEGER,
                type: gl.UNSIGNED_BYTE
            };

            // -- Init Texture

            gl.activeTexture(gl.TEXTURE0);

            var textures = new Array(TextureTypes.MAX);
            var i = 0;
            for (i = 0; i < TextureTypes.MAX; ++i) {
                textures[i] = gl.createTexture();
                gl.bindTexture(gl.TEXTURE_2D, textures[i]);
                gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
                gl.texImage2D(gl.TEXTURE_2D, 0, textureFormats[i].internalFormat, textureFormats[i].format, textureFormats[i].type, image);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, 0);
                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, 0);
            }

            // -- Render
            gl.clearColor(0.0, 0.0, 0.0, 1.0);
            gl.clear(gl.COLOR_BUFFER_BIT);

            gl.bindVertexArray(vertexArray);

            var matrix = new Float32Array([
                1.0, 0.0, 0.0, 0.0,
                0.0, 1.0, 0.0, 0.0,
                0.0, 0.0, 1.0, 0.0,
                0.0, 0.0, 0.0, 1.0
            ]);

            // Normalized textures
            gl.useProgram(programNormalized);
            gl.uniformMatrix4fv(mvpNormalizedLocation, false, matrix);
            gl.uniform1i(diffuseNormalizedLocation, 0);

            for (i = 0; i < TextureTypes.RGB8UI; ++i) {
                gl.viewport(viewport[i].x, viewport[i].y, viewport[i].z, viewport[i].w);
                gl.bindTexture(gl.TEXTURE_2D, textures[i]);
                gl.drawArrays(gl.TRIANGLES, 0, 6);
            }

            // Unsigned int textures
            gl.useProgram(programUint);
            gl.uniformMatrix4fv(mvpUintLocation, false, matrix);
            gl.uniform1i(diffuseUintLocation, 0);

            for (i = TextureTypes.RGB8UI; i < TextureTypes.MAX; ++i) {
                gl.viewport(viewport[i].x, viewport[i].y, viewport[i].z, viewport[i].w);
                gl.bindTexture(gl.TEXTURE_2D, textures[i]);
                gl.drawArrays(gl.TRIANGLES, 0, 6);
            }

            // Delete WebGL resources
            gl.deleteBuffer(vertexPosBuffer);
            gl.deleteBuffer(vertexTexBuffer);
            for (i = 0; i < TextureTypes.MAX; ++i) {
                gl.deleteTexture(textures[i]);
            }
            gl.deleteProgram(programUint);
            gl.deleteProgram(programNormalized);
            gl.deleteVertexArray(vertexArray);
        });
    })();
    </script>
    <div id="highlightedLines"  style="display: none">#L185-L270</div>

</body>

</html>
